/*
	Формирование выходов
	Взято у Андрея
*/
#include "defines.h"

OUT Out_time;
unsigned char flag_error;

/*
	Здесь из строки формируем укороченную версию логического выражения 
*/
void out_arry(unsigned char * mon_out)
{
 OUT *p = &Out_time;
 unsigned char *p_out; 
 unsigned char *p_arry = mon_out;
 unsigned char flag_i = 0, flag_o = 0, flag_OR = 0, flag_AND = 0, flag_NOT = 0;
 unsigned char flag_a = 0, flag_adc = 0;
 unsigned char count = 0, i = 0, j = 0;
	unsigned char temp;
 for(;;)
   {
		 temp = *p_arry++;
    switch(temp)
      {
       case 'i':
                flag_i = 1;
                POISK_ERROR;
                break;
       case 'o':
                flag_o = 1;
                POISK_ERROR;
                break;
       case 'a':
                flag_a = 1;
                flag_adc = 1;
                break;
       case '1':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 1;
                if(flag_a){*p_out++ = A1; flag_a = 0;} 
                if(flag_i){*p_out++ = I1; flag_i = 0;}
                if(flag_o){p_out = &p->arry_mon1[0];*p_out++ = O1;flag_o = 0;p->flag_o1 = 1;} 
                break;
       case '2':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 2;
                if(flag_a){*p_out++ = A2; flag_a = 0;}
                if(flag_i){*p_out++ = I2;flag_i = 0;}
                if(flag_o){p_out = &p->arry_mon2[0];*p_out++ = O2;flag_o = 0;p->flag_o2 = 1;}
                break;
       case '3':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 3;
                if(flag_a){*p_out++ = A3; flag_a = 0;}
                if(flag_i){*p_out++ = I3;flag_i = 0;}
                if(flag_o){p_out = &p->arry_mon3[0];*p_out++ = O3;flag_o = 0;p->flag_o3 = 1;}
                break;
       case '4':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 4;
                if(flag_a){*p_out++ = A4; flag_a = 0;}
                if(flag_i){*p_out++ = I4;flag_i = 0;}
                break;
       case '5':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 5;
                if(flag_i){*p_out++ = I5;flag_i = 0;}
                break;
       case '6':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 6;
                if(flag_i){*p_out++ = I6;flag_i = 0;}
                break;
       case '7':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 7;
                if(flag_i){*p_out++ = I7;flag_i = 0;}
                break;
       case '8':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 8;
                if(flag_i){*p_out++ = I8;flag_i = 0;}
                break;
       case '9':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 9;
                break;
       case '0':
                POISK_ERROR;
                if(!flag_a && flag_adc) *p_out++ = 0;
                break;
       case '(':
                *p_out++ = '(';
                break;
       case '[':
                *p_out++ = '[';
                break;
       case ']':
                *p_out++ = ']';
                flag_adc = 0;
                break;
       case ')':
                *p_out++ = ')';
                break;
       case '>':
                if(flag_adc) *p_out++ = '>';
                else flag_error = ERROR;
                break;
       case '<':
                if(flag_adc) *p_out++ = '<';
                else flag_error = ERROR;
                break;
       case 'O':
                if(flag_NOT==1)flag_NOT++;
                else flag_OR++;
                break;
       case 'R':
                if(flag_OR) {*p_out++ = OR;flag_OR = 0;}
                else flag_error = ERROR;
                break;
       case 'N':
                if(flag_AND == 1)flag_AND++;
                else if(!flag_NOT)flag_NOT++;
                     else flag_error = ERROR;
                break;
       case 'A':
                flag_AND++;
                break;
       case 'D':
                if(flag_AND == 2){*p_out++ = AND;flag_AND = 0;}
                else flag_error = ERROR;
								break;
       case 'T':
                if(flag_NOT==2){*p_out++ = NOT;flag_NOT = 0;}
                else flag_error = ERROR;
                break;
       case '=':
                *p_out++ = '=';
                break;
       case 0x20:
       case 0x0D:
                 break;
       case 0x0A:
                *p_out++ = 0x0A;
                count++;
                if(count==3){flag_error = OK;
                              #ifdef DEBUG_
                              printf("out1=\n");
                              for(i=0;i<100;i++,j++)
                                 {printf("  %X",p->arry_mon1[i]);
                                 if(j>=15){printf("\n");j=0;}}
                                 printf("out2=\n");
                              for(i=0,j=0;i<100;i++,j++)
                                 {printf("  %X",p->arry_mon2[i]);
                                 if(j>=15){printf("\n");j=0;}}
                                 printf("out3=\n");
                              for(i=0,j=0;i<100;i++,j++)
                                 {printf("  %X",p->arry_mon3[i]);
                                 if(j>=15){printf("\n");j=0;}}
                              #endif
                             return;}
                break;
       default:
                flag_error = ERROR; 
                break;
      }
     if(flag_error == ERROR){
                             
                             Out_time.error_out = 1;
                             printf("Out_time.error_out3=%d\n",Out_time.error_out);
                             return;}
   }
}


//------------------------------------------------------------------------
//q-начало массива, w-конец массива,flag-OR,AND,NOT
//*p-массив,*p_l-входа
//------------------------------------------------------------------------
static void preob(U8 q,U8 w,U8 *p_l,U8 *p,U8 flag)
{
 U8 flag_not = 0,flag_or = 0,flag_and = 0,flag_i = 0;
 U8 a = 0, b = 0, i = 0, c = 0;
  for(i = q; i < w; i++)
   {
    switch(p[i])
      {
       case 0:
               a = 0;
               if(flag_not){p[i] = 1;flag_not = 0;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;b = 0;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case 1:
               a = 1;
               if(flag_not){p[i] = 0;flag_not = 0;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;b = 1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case OR:
               if(flag == OR){flag_or = 1;p[i] = 0x20;} 
               else if(flag_i)flag_i = 0;
               break;
       case AND:
               if(flag == AND){flag_and = 1;p[i] = 0x20;}
               else if(flag_i)flag_i = 0;
               break;
       case NOT:
               if(flag == NOT){flag_not = 1;p[i] = 0x20;}
               break;
       case I1:
               a = *p_l & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;} 
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;b = *p_l & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I2:
               a = *p_l>>1 & 0x1;
								if(flag_not)
								{
									flag_not = 0;
									p[i] = ~a & 0x01;
								}
								else if((flag == OR || flag == AND)&& !flag_i)
								{
									flag_i = 1;
									b = *p_l>>1 & 0x1;
									c = i;
								}
                else if(flag_or && flag_i)
								{
									flag_i = 0;
									p[i] = b | a;
									p[c]=0x20;
									flag_or = 0;
									i = q;
								}
                else if(flag_and && flag_i)
								{
									flag_i = 0;
									p[i] = b & a;
									p[c]=0x20;
									flag_and = 0;
									i = q;
								}
               break;
       case I3:
               a = *p_l>>2 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;} 
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>2 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I4:
               a = *p_l>>3 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>3 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I5:
               a = *p_l>>4 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>4 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I6:
               a = *p_l>>5 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>5 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I7:
               a = *p_l>>6 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>6 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break;
       case I8:
               a = *p_l>>7 & 0x1;
               if(flag_not){flag_not = 0;p[i] = ~a & 0x01;}
               else if((flag == OR || flag == AND)&& !flag_i){flag_i = 1;p[i] = 0x20;b = *p_l>>7 & 0x1;c = i;}
                    else if(flag_or && flag_i){flag_i = 0;p[i] = b | a;p[c]=0x20;flag_or = 0;i = q;}
                         else if(flag_and && flag_i){flag_i = 0;p[i] = b & a;p[c]=0x20;flag_and = 0;i = q;}
               break; 
       case 0x20:
                 break;
       case 0x0A:
                 return;
      }
  }
}
//------------------------------------------------------------------------
static void preob_adc(U8 j1, U8 j2, unsigned char *p)
{
 U8 flag_a1 = 0, flag_a2 = 0, flag_a3 = 0, flag_a4 = 0;
 U8 i = 0;
 U8 flag_1 = 0, flag_2 = 0;
 U8 count = 0, n[5];
 unsigned int result = 0, temp = 0;
 for(i = j1; i < j2; i++)
 {
  switch (p[i])
  {
   case 0:
   case 1:
   case 2:
   case 3:
   case 4:
   case 5:
   case 6:
   case 7:
   case 8:
   case 9:
              n[++count] = p[i];
              p[i] = 0x20;
              break;
   case A1:
              flag_a1 = 1;
              result = adcAverage.adc1;
              p[i] = 0x20;
              break;
   case A2:
              flag_a2 = 1;
              result = adcAverage.adc2;
              p[i] = 0x20;
              break;
   case A3:
              flag_a3 = 1;
              result = adcAverage.adc3;
              p[i] = 0x20;
              break;
   case A4:
              flag_a4 = 1;
              result = adcAverage.adc4;
              p[i] = 0x20;
              break;
   case '>':
              flag_1 = 1;
              p[i] = 0x20;
              break;
   case '<':
              flag_2 = 1;
              p[i] = 0x20;
              break;
   case 0x20:
              break;
   case 0x0A:
              return;
  }//switch
 }//for
 switch (count)
 {
  case 1:
         temp = n[1];
         break;
  case 2:
         temp = n[1] * 10 + n[2];
         break;
  case 3:
         temp = n[1] * 100 + n[2] * 10 + n[3];
         break;
  case 4:
         temp = n[1] * 1000 + n[2] * 100 + n[3] * 10 + n[4]; 
         break;
 }
 if(flag_1)
 {	 
  if(result > temp) 
		p[j2] = 1; 
  else
		p[j2] = 0;
 }
 if(flag_2)
 {
  if(result < temp) 
		p[j2] = 1;
	else 
		p[j2] = 0;
 }
}
//------------------------------------------------------------------------
static unsigned char indikator_out(unsigned char arry_[],unsigned char *p_l)
{
 U8 i = 0, j1 = 0, j2 = 0, arry[100], flag = 0, flag1 = 0;
 U8 result = 0, k = 0, m = 0;
 unsigned char *p = arry;
 for(; i < 100; i++)
  arry[i] = arry_[i];

 t1:
 for(i = 0; i < 100; i++)
  {
   if(p[i] == 0x0A){flag = 0; i = 100; break;}
   if(p[i] == '('){flag = 1; j1 = i; p[i] = 0x20;}
   if(p[i] == ')' && flag){j2 = i; p[i] = 0x20; break;}
   if(p[i] == '[') {flag1 = 1; j1 = i; p[i] = 0x20;}
   if(p[i] == ']' && flag1) {j2 = i; p[i] = 0x20; break;}
  }
 if(flag1){flag1 = 0; preob_adc(j1, j2, p);}
 if(flag){flag = 0; preob(j1, j2, p_l, p, NOT);
                    preob(j1, j2, p_l, p, AND);
                    preob(j1, j2, p_l, p, OR);}
                              #ifdef DEBUG_
                                printf("_out_=\n");
                              for(k = 0; k < 100; k++, m++)
                                 {printf("  %X", p[k]);
                                 if(m>=15){printf("\n"); m = 0;}}
                              #endif
 if(i < 99) goto t1;
 j1 = 0; j2 = 99;
 preob(j1, j2, p_l, p, NOT);
 preob(j1, j2, p_l, p, AND);
 preob(j1, j2, p_l, p, OR);
                              #ifdef DEBUG_
                                printf("_out_end=\n");
                              for(k = 0; k < 100; k++, m++)
                                 {printf("  %X", p[k]);
                                 if(m >= 15){printf("\n"); m = 0;}}
                              #endif
                                 
 for(i = 0; i < 100; i++)
  {
   if(p[i] == 0x0A) break;
   if(p[i] == 1) return 1;
   if(p[i] == 0) return 0;
  }
 return result;
}
//-----------------------------------------------------------------------
void mon_out_(unsigned char p_lines)
{
 static unsigned long rtc1 = 0,rtc2 = 0,rtc3 = 0;
 static unsigned char flag1 = 0,flag2 = 0,flag3 = 0;
 unsigned long rtc_now;
	U64 ticks;
 unsigned char result = 0;
 
	if(Out_time.error_out)
	{
		//Led.error_cd_out = 1;
		return;
	}
 else 
		//Led.error_cd_out = 0;

 rtc_now = SystemTick;

 //------------------------------------------------------------------------------
 //Выход 1
 //printf("flag_o1=%d\n",Out_time.flag_o1);
 if(Out_time.flag_o1) 
	 result = indikator_out(Out_time.arry_mon1,&p_lines);
 else 
	 result = 0;

 printf("out1: %d timeout: %d\r\n",result,Out_time.time_out1);
 if(result && !flag1)
 {
	flag1 = 1;
	rtc1 = rtc_now;
 }
 else if(!result)
 {
	flag1 = 0;
	//OUT1_0;
	//Led.out1 = 0;
	OUTPUT1_LOW;
 }

	//Отложенное задание значение выходного сигнала
	if(flag1 && (rtc_now-rtc1) >= (Out_time.time_out1*60*1000))
	{
		//OUT1_1;
		//Led.out1 = 1;
		OUTPUT1_HIGH;
	}

 //------------------------------------------------------------------------------
 //Выход 2
 //printf("flag_o2=%d\n",Out_time.flag_o2);
	if(Out_time.flag_o2)
		result = indikator_out(Out_time.arry_mon2,&p_lines);
	else 
		result = 0;

	printf("out2: %d timeout: %d\r\n",result,Out_time.time_out2);
	
	if(result && !flag2)
	{
		flag2 = 1;
		rtc2 = rtc_now;
	}
	else if(!result)
	{
		flag2 = 0;
		//OUT2_0;
		//Led.out2 = 0;
		OUTPUT2_LOW;
	}
	
	if(flag2 && (rtc_now-rtc2) >= (Out_time.time_out2*60*1000))
	{
		//OUT2_1;
		//Led.out2 = 1;1
		OUTPUT2_HIGH;
	}

 //------------------------------------------------------------------------------
 //Выход 3
 //printf("flag_o3=%d\n",Out_time.flag_o3);
	if(Out_time.flag_o3) 
		result = indikator_out(Out_time.arry_mon3,&p_lines);
	else 
		result = 0;

	printf("out3: %d timeout: %d\r\n",result,Out_time.time_out3);
	
	if(result && !flag3)
	{
		flag3 = 1;	
		rtc3 = rtc_now;
	}
	else if(!result)
	{
		flag3 = 0;
		//OUT3_0;
		//Led.out3 = 0;
		OUTPUT3_LOW;
	}
	
	if(flag3 && (rtc_now-rtc3) >= (Out_time.time_out3*60*1000))
	{
		//OUT3_1;
		//Led.out3 = 1;
		OUTPUT3_HIGH;
	}
}

